package com.example.blog.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.blog.base.CurrentAccount;
import com.example.blog.entity.Follow;
import com.example.blog.entity.SysUser;
import com.example.blog.entity.dto.user.LoginDTO;
import com.example.blog.entity.dto.user.NewMsgCount;
import com.example.blog.entity.dto.user.PageQueryDTO;
import com.example.blog.entity.dto.user.UpdateInfoDTO;
import com.example.blog.entity.vo.user.LoginUserVO;
import com.example.blog.entity.vo.user.PageQueryVO;
import com.example.blog.entity.vo.user.UserInfoVO;
import com.example.blog.exception.BizAssertUtils;
import com.example.blog.jwt.JwtUtil;
import com.example.blog.mapper.SysUserMapper;
import com.example.blog.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.blog.util.BeanUtils;
import com.example.blog.util.CurrentUserUtils;
import com.example.blog.util.Md5Util;
import com.example.blog.util.RedisCacheUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统用户表 服务实现类
 * </p>
 *
 * @author wlh
 * @since 2024-01-10
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {


    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Autowired
    private FollowService followService;

    @Autowired
    private LikeService likeService;

    @Autowired
    @Lazy
    private CommentService commentService;

    @Autowired
    private ReplyService replyService;

    @Autowired
    private FavoritesService favoritesService;

    @Autowired
    @Lazy
    private ArticleService articleService;

    @Override
    public LoginUserVO login(LoginDTO loginDTO) {
        SysUser sysUser = getByUsername(loginDTO.getUsername());
        BizAssertUtils.notNull(sysUser, "账号或密码错误");

        Boolean b = Md5Util.decrypt(sysUser.getPassword(), loginDTO.getPassword());
        BizAssertUtils.isTrue(b, "账号或密码错误");

        String token = JwtUtil.createJWT(sysUser.getUsername());

        redisCacheUtil.set(token, CurrentAccount.userToCurrentAccount(sysUser,token));
        sysUser.setPassword(null);
        LoginUserVO loginUserVO = BeanUtils.copyProperties(sysUser, LoginUserVO.class);
        loginUserVO.setToken(token);

        return loginUserVO;
    }

    @Override
    public void logout() {
        CurrentAccount account = CurrentUserUtils.clear();
        redisCacheUtil.del(account.getToken());
    }

    @Override
    public Page<PageQueryVO> adminPage(PageQueryDTO pageQueryDTO) {
        Page<SysUser> sysUserPage = new Page<>(pageQueryDTO.getPageCurrent(), pageQueryDTO.getPageSize());

        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<SysUser>();

        queryWrapper.like(StrUtil.isNotBlank(pageQueryDTO.getUsername()), SysUser::getUsername, pageQueryDTO.getUsername());

        page(sysUserPage,queryWrapper);

        return BeanUtils.copyPage(sysUserPage, PageQueryVO.class);
    }


    @Override
    public SysUser getByUsername(String username) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, username);

        return getOne(queryWrapper);
    }

    @Override
    public void updateInfo(UpdateInfoDTO updateInfoDTO) {
        SysUser sysUser = getByIdNotNull(updateInfoDTO.getId());
        BeanUtils.copyProperties(updateInfoDTO, sysUser);
        updateById(sysUser);
    }


    @Override
    public SysUser getByIdNotNull(Serializable id) {
        SysUser sysUser = getById(id);
        BizAssertUtils.notNull(sysUser, "该用户不存在");
        return sysUser;
    }

    @Override
    public Page<UserInfoVO> search(String value, Integer current, Integer size) {
        Page<SysUser> userPage = new Page<>(current, size);
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(SysUser::getNickname, value);
        page(userPage, queryWrapper);
        List<SysUser> records = userPage.getRecords();
        List<Long> uids = records
                .stream()
                .map(SysUser::getId)
                .collect(Collectors.toList());
        if (uids.isEmpty()) {
            return new Page<>();
        }
        List<UserInfoVO> collect;
        if (CurrentUserUtils.isLogin()) {
            List<Follow> follows = followService.getListByUser(CurrentUserUtils.currentUser().getId(), uids);
            Map<Long, Follow> map = follows
                    .stream()
                    .collect(Collectors.toMap(Follow::getFollowingId, Function.identity()));
            collect = records
                    .stream()
                    .map(i -> {
                        UserInfoVO userInfoVO = BeanUtils.copyProperties(i, UserInfoVO.class);
                        Follow follow = map.get(i.getId());
                        if (follow != null){
                            userInfoVO.setIsFollow(true);
                        } else {
                            userInfoVO.setIsFollow(false);
                        }
                        return userInfoVO;
                    })
                    .collect(Collectors.toList());
        } else {
            collect = records
                    .stream()
                    .map(i -> {
                        UserInfoVO userInfoVO = BeanUtils.copyProperties(i, UserInfoVO.class);
                        userInfoVO.setIsFollow(false);
                        return userInfoVO;
                    })
                    .collect(Collectors.toList());
        }
        Page<UserInfoVO> page = new Page<UserInfoVO>();
        BeanUtils.copyProperties(userPage, page);
        page.setRecords(collect);
        return page;

    }

    @Override
    public NewMsgCount newMsgCount() {
        CurrentAccount currentUser = CurrentUserUtils.currentUser();

        // 关注
        Long followCount = followService.getNewCountByUser(currentUser.getId());
        // 二级评论
        Long replyCount = replyService.getNewCountByUser(currentUser.getId());
        // 一级评论
        Long commentCount = commentService.getNewCountByUser(currentUser.getId());
        // 点赞
        Long likeCount = likeService.getNewCountByUser(currentUser.getId());
        // 收藏
        Long favoritesCount = favoritesService.getNewCountByUser(currentUser.getId());

        return new NewMsgCount(followCount, likeCount, favoritesCount, commentCount + replyCount);

    }

    @Override
    public void register(LoginDTO loginDTO) {
        String encode = Md5Util.encode(loginDTO.getPassword());
        SysUser sysUser = BeanUtils.copyProperties(loginDTO, SysUser.class);
        sysUser.setPassword(encode);
        sysUser.setRole("USER");
        sysUser.setNickname(loginDTO.getUsername());

        save(sysUser);
    }

    @Override
    public UserInfoVO getUserInfo(Long id) {
        SysUser sysUser = getByIdNotNull(id);
        Map<String, Object> map = articleService.countByUser(id);

        Long f = followService.countByUser(id);
        UserInfoVO userInfoVO = BeanUtils.copyProperties(sysUser, UserInfoVO.class);
        BigDecimal views = (BigDecimal) map.getOrDefault("views", BigDecimal.ZERO);
        userInfoVO.setArticleCount((Long) map.getOrDefault("counts",0L));
        userInfoVO.setReadCount(views.longValue());
        userInfoVO.setFollowCount(f);
        userInfoVO.setIsFollow(isFollow(id));
        return userInfoVO;
    }

    @Override
    public Boolean isFollow(Long userId) {
        if (CurrentUserUtils.isLogin()) {
            return followService.isFollowed(CurrentUserUtils.currentUser().getId(), userId);
        } else {
            return false;
        }

    }
}
